package utils

import "time"

// 创建一个队列类型
type Queue[q any] struct {
	//队列长度
	len int
	//队列头
	head *QueueNode[q]
	//队列尾
	tail *QueueNode[q]
}

// 创建一个队列node
type QueueNode[q any] struct {
	//当前节点的值
	value q
	//下一个节点
	next *QueueNode[q]
	//上一个节点
	prev *QueueNode[q]
}

// 创建一个队列
func NewQueue[q any]() *Queue[q] {
	return &Queue[q]{}
}

// 创建一个队列node
func newQueueNode[q any](value q) *QueueNode[q] {
	return &QueueNode[q]{value: value}
}

// 获取队列长度
func (q *Queue[Q]) Len() int {
	return q.len
}

// 获取队列头
func (q *Queue[Q]) Head() *QueueNode[Q] {
	return q.head
}

// 获取队列尾
func (q *Queue[Q]) Tail() *QueueNode[Q] {
	return q.tail
}

// 获取队列头的值
func (q *Queue[Q]) HeadValue() Q {
	return q.head.value
}

// 获取队列尾的值
func (q *Queue[Q]) TailValue() Q {
	return q.tail.value
}

// 弹出队列头
func (q *Queue[Q]) PopHead() Q {
	if q.head == nil {
		var a Q
		return a
	}
	value := q.head.value
	q.head = q.head.next
	if q.head != nil {
		q.head.prev = nil //这里需要将上一个节点置空,否则会导致内存泄漏
	}
	q.len--
	return value
}

// 弹出队列尾
func (q *Queue[Q]) PopTail() Q {
	if q.tail == nil {
		var a Q
		return a
	}
	value := q.tail.value
	q.tail = q.tail.prev
	if q.tail != nil {
		q.tail.next = nil //这里需要将下一个节点置空,否则会导致内存泄漏
	}
	q.len--
	return value
}

// 添加队列头
func (q *Queue[Q]) PushHead(value Q) {
	node := newQueueNode[Q](value)
	if q.head == nil {
		q.head = node
		q.tail = node
	} else {
		node.next = q.head
		q.head.prev = node
		q.head = node
	}
	q.len++
}

// 添加队列尾
func (q *Queue[Q]) PushTail(value Q) {
	node := newQueueNode[Q](value)
	if q.tail == nil {
		q.head = node
		q.tail = node
	} else {
		node.prev = q.tail
		q.tail.next = node
		q.tail = node
	}
	q.len++
}

// 遍历队列
func (q *Queue[Q]) Range(f func(index int, value Q) bool) {
	for i, node := 0, q.head; node != nil; i, node = i+1, node.next {
		if !f(i, node.value) {
			break
		}
	}
}

// 获取队列所有值
func (q *Queue[Q]) Values() []Q {
	var values []Q
	for i, node := 0, q.head; node != nil; i, node = i+1, node.next {
		values = append(values, node.value)
	}
	return values
}

// 弹出队列尾部,如果队列是空那么等待,直到队列不为空获取队列尾部
func (q *Queue[Q]) PopTailWait() Q {
	for {
		if q.tail != nil {
			return q.PopTail()
		}
		time.Sleep(time.Millisecond * 10)
	}
}

// 弹出队列尾部,如果队列是空那么等待一定时间,如果在等待时间内队列不为空获取队列尾部,如果等待时间到了那么返回空
func (q *Queue[Q]) PopTailWaitTime(millisecond int) Q {
	var num int
	for {
		if q.tail != nil {
			return q.PopTail()
		}
		time.Sleep(time.Millisecond * 10)
		num += 10
		if num >= millisecond {
			var a Q
			return a
		}
	}
}

// 弹出队列头部,如果队列是空那么等待,直到队列不为空获取队列头部
func (q *Queue[Q]) PopHeadWait() Q {
	for {
		if q.head != nil {
			return q.PopHead()
		}
		time.Sleep(time.Millisecond * 10)
	}
}

// 弹出队列头部,如果队列是空那么等待一定时间,如果在等待时间内队列不为空获取队列头部,如果等待时间到了那么返回空
func (q *Queue[Q]) PopHeadWaitTime(millisecond int) Q {
	var num int
	for {
		if q.head != nil {
			return q.PopHead()
		}
		time.Sleep(time.Millisecond * 10)
		num += 10
		if num >= millisecond {
			var a Q
			return a
		}
	}
}
